﻿using AntdUI;
using AntdUI.In;
using DynamicData;
using MySqlX.XDevAPI.Relational;
using PosClient.Delegates;
using PosClient.Interfaces;
using PosClient.Model;
using PosClient.Service;
using PosClient.ViewModel;
using Splat;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace PosClient.Controls
{
    public partial class PluGrid : UserControl, INotifyPropertyChanged
    {
        public event GridDataEventHandler GridDataEvent;

        public event GridIndexEventHandler GridIndexEvent;

        public event RowClickEventHandler RowClickEvent;

        public PluGrid()
        {
            InitializeComponent();
            _factory.SetCreationType<PluRowPro>();
            InitEvent();
        }

        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        [Localizable(true)]
        [MergableProperty(false)]
        [Description("数据源集合"), Category("外观"), DefaultValue(false)]
        public BindingList<Plu> DataSource
        {
            get
            {
                return _DataSource;
            }
            set
            {
                if (_DataSource == value) return;
                _DataSource = value;
                ReloadGridView();
                NotifyPropertyChanged(nameof(_DataSource));
            }
        }
        private BindingList<Plu> _DataSource = new BindingList<Plu>();

        [Description("当前行索引，可通过此属性控制选中行"), Category("外观"), DefaultValue(false)]
        public int Index
        {
            get
            {
                return _Index;
            }
            set
            {
                if (_Index == value) return;
                _Index = value;
                UpdateChoose(_Index);
                NotifyPropertyChanged();
            }

        }
        private int _Index;

        [Description("是否简化行"), Category("外观"), DefaultValue(false)]
        public bool Screen
        {
            get => _Screen;
            set
            {
                if (_Screen == value) return;
                _Screen = value;
                Invalidate();
                NotifyPropertyChanged();
            }
        }
        private bool _Screen;

        [Description("购物车图标Svg"), Category("外观"), DefaultValue("")]
        public string Svg
        {
            get => _Svg;
            set
            {
                if (_Svg == value) return;
                _Svg = value;
                total1.Svg = !string.IsNullOrEmpty(_Svg) ? "" : _Svg;
                Invalidate();
                NotifyPropertyChanged();
            }
        }
        private string _Svg;

        [Description("总优惠"), Category("外观"), DefaultValue("")]
        public decimal TotalDiscount
        {
            get => _TotalDiscount;
            set
            {
                if (_TotalDiscount == value) return;
                _TotalDiscount = value;
                total1.TotalDiscount = _TotalDiscount;
                Invalidate();
                NotifyPropertyChanged();
            }
        }
        private decimal _TotalDiscount;

        [Description("总额"), Category("外观"), DefaultValue("")]
        public decimal TotalAmount
        {
            get => _TotalAmount;
            set
            {
                if (_TotalAmount == value) return;
                _TotalAmount = value;
                total1.TotalAmount = _TotalAmount;
                Invalidate();
                NotifyPropertyChanged();
            }
        }
        private decimal _TotalAmount;

        [Description("总数"), Category("外观"), DefaultValue("")]
        public decimal TotalCount
        {
            get => _TotalCount;
            set
            {
                if (_TotalCount == value) return;
                _TotalCount = value;
                total1.TotalCount = _TotalCount;
                Invalidate();
                NotifyPropertyChanged();
            }
        }
        private decimal _TotalCount;

        //行的抽象工厂
        private readonly RowFactory _factory = new RowFactory();


        private void UpdateChoose(int index)
        {
            if (index > -1 && stackPanel1.Controls.Count > 0 && stackPanel1.Controls.Count > index)
            {
                RowChoose(stackPanel1.Controls[index], null);
            }
        }

        private void ReloadGridView()
        {
            stackPanel1.Controls.Clear();
            if (_DataSource != null)
            {
                for (int i = 0; i < _DataSource.Count; i++)
                {
                    var newRow = _factory.CreateNewRow();
                    newRow.ViewModel.Plu = _DataSource[i];
                    newRow.RowDispose += Row_Disposed;
                    newRow.ViewModel.Index = i;
                    newRow.ViewModel.Screen = !Screen;
                    newRow.RowClick += RowChoose;
                    newRow.RowValue += RowValue;
                    stackPanel1.Controls.Add(newRow.control);
                    RowChoose(newRow.control, null);
                }
                Summary();
            }
            this.Refresh();
            this.Invalidate();
        }

        public void DataSource_ListChanged(object sender, ListChangedEventArgs e)
        {
            switch (e.ListChangedType)
            {
                case ListChangedType.ItemAdded:
                    var newRow = _factory.CreateNewRow();
                    newRow.ViewModel.Plu = _DataSource[_DataSource.Count-1];
                    newRow.RowDispose += Row_Disposed;
                    newRow.ViewModel.Index = _DataSource.Count - 1;
                    newRow.ViewModel.Screen = !Screen;
                    newRow.RowClick += RowChoose;
                    newRow.RowValue += RowValue;
                    stackPanel1.Controls.Add(newRow.control);
                    RowChoose(newRow.control, null);
                    break;
                case ListChangedType.Reset:
                    stackPanel1.Controls.Clear();
                    break;
                case ListChangedType.ItemDeleted:
                    if (stackPanel1.Controls.Count > 0)
                    {
                        for (int i = 0; i < stackPanel1.Controls.Count; i++)
                        {
                            IRow rows = stackPanel1.Controls[i] as IRow;
                            var plu = rows.ViewModel.Plu;
                            if (_DataSource.Where(x => x.PluCode == plu.PluCode && x.PluName == plu.PluName && x.Tag == plu.Tag).Count() == 0)
                            {
                                _DataSource.Remove(plu);
                                stackPanel1.Controls.Remove(rows.control);
                            }
                        }
                        if (stackPanel1.Controls.Count > 0)
                        {
                            ResetIndex();
                            RowChoose(stackPanel1.Controls[stackPanel1.Controls.Count - 1], null);
                        }
                    }
                    break;
            }
            Summary();
        }

        private void Summary()
        {
            TotalAmount = DataSource.Sum(x => x.Amount);
            TotalDiscount = DataSource.Sum(x => x.DisAmount);
            TotalCount = DataSource.Sum(x => x.Count);
        }
        public void PosGrid_KeyUp(Keys e)
        {
            if (e == Keys.Down)
            {
                if (_Index < stackPanel1.Controls.Count && _Index > 0)
                {
                    RowChoose(stackPanel1.Controls[_Index - 1], null);
                }
                else
                {
                    RowChoose(stackPanel1.Controls[stackPanel1.Controls.Count - 1], null);
                }
            }
            else if (e == Keys.Up)
            {
                if (_Index == stackPanel1.Controls.Count - 1)
                {
                    RowChoose(stackPanel1.Controls[0], null);
                }
                else
                {
                    RowChoose(stackPanel1.Controls[_Index + 1], null);
                }
            }
        }

        private void RowChoose(object sender, EventArgs e)
        {
            var activeControl = sender as IRow;
            foreach (Control control in stackPanel1.Controls)
            {
                var item = control as IRow;
                if (item != null)
                {
                    item.ViewModel.IsChecked = false;
                }
            }
            _Index = activeControl.ViewModel.Index;
            GridIndexEvent?.Invoke(_Index, e);//通知更新索引
            activeControl.ViewModel.IsChecked = true;
            stackPanel1.ScrollControlIntoView(activeControl.control);
        }

        private void ResetIndex()
        {
            for(int i = 0; i < stackPanel1.Controls.Count; i ++)
            {
                var control = stackPanel1.Controls[i];
                if (control is IRow)
                {
                    var item = control as IRow;
                    if (item != null)
                    {
                        item.ViewModel.Index = i;
                    }
                }
            }
        }

        private void RowValue(object sender, EventArgs e)
        {
            GridDataEvent?.Invoke(sender, e);
        }

        private void Row_Disposed(object sender, EventArgs e)
        {
            var activeControl = sender as IRow;
            _DataSource.Remove(activeControl.ViewModel.Plu);
            GridDataEvent?.Invoke(sender, e);
            ResetIndex();
        }

        private void InitEvent()
        {
            this.button_handoff.Click += (s, e) =>
            { 
                _factory.ChangeRow();
                ReloadGridView();
            };

            this.button_clear.Click += (s, e) =>
            {
                _DataSource.Clear();
                GridDataEvent?.Invoke(s, e);
            };

            this.total1.RowClick += (s, e) =>
            {
                RowClickEvent?.Invoke(s, e);
            };
        }


        public event PropertyChangedEventHandler PropertyChanged;
        private void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); //实现通知刷新
        }
    }
}
